print(type(123))
print(type("str"))
print(type(None))

# 判断基本数据类型可以直接写int，str等
print(type(123) == int)
print(type('abc') == str)

import types


# 但如果要判断一个对象是否是函数怎么办？可以使用types模块中定义的常量：
def fn():
    pass


print(type(fn) == types.FunctionType)
print(type(abs) == types.BuiltinFunctionType)
print(type(lambda x: x) == types.LambdaType)

print(type((x for x in range(10))) == types.GeneratorType)


class Animal(object):
    pass


class Dog(Animal):
    pass


class Husky(Dog):
    pass


a = Animal()
d = Dog()
h = Husky()

print('----------------------')
print(isinstance(h, Husky))
print(isinstance(h, Dog))
print(isinstance(h, Animal))

print(isinstance(d, Dog) and isinstance(d, Animal))

print(isinstance(d, Husky))

print(isinstance('a', str))
print(isinstance(123, int))
print(isinstance(b'a', bytes))

print(isinstance(d, (Husky, Dog)))
print(isinstance([1, 2, 3], (list, tuple)))
print(isinstance((1, 2, 3), (list, tuple)))

print(dir('ABC'))
print(dir(123))
print(dir([]))
print(dir(()))

# 类似__xxx__的属性和方法在Python中都是有特殊用途的，比如__len__方法返回长度
print(len('ABC'))
print('ABC'.__len__())

class MyDog(object):
    def __len__(self):
        return 100


dog = MyDog()
print(len(dog))


print('ABC'.lower())


# getattr()  setattr()  hasattr()

class MyObject(object):
    def __init__(self):
        self.x = 9

    def power(self):
        return self.x * self.x


obj = MyObject()

print('attr --------------------=')
print(hasattr(obj, 'x'))
print(obj.x)
print(hasattr(obj, 'y'))
setattr(obj, 'y', 19)
print(hasattr(obj, 'y'))
print(getattr(obj, 'y'))
print(obj.y)

# getattr(obj, 'z')
# print(obj.z)

getattr(obj, 'z', 404)

print(hasattr(obj, 'power'))
fn = getattr(obj, 'power')
print(fn())
